#pragma once

#include <deque>
#include "Message.h"
#include "MessageFwd.h"
#include <boost/asio.hpp>
#include <boost/function.hpp>
#pragma warning (disable: 4512)
#include <boost/thread.hpp>
#pragma warning (default: 4512)


typedef boost::function<void (const Message&)> GalconClientErrorHandler;
typedef boost::function<void (const Message&)> GalconClientMessageHandler;

typedef boost::shared_ptr<boost::asio::io_service> IOServicePtr;

typedef std::deque<Message> MessagesDeque;

using boost::asio::ip::tcp;

class GalconClient
{
public:
   GalconClient(const std::string& address, 
                const std::string& port,
                GalconClientErrorHandler onConnectFailed, 
                GalconClientMessageHandler newMessageHandler);
   ~GalconClient(void);
   void Connect();
   void Send(const Message&);
   void Disconnect();

private:

   void handleConnect(const boost::system::error_code& error, 
                      tcp::resolver::iterator endpoint_iterator);
   void handle_read_header(const boost::system::error_code& error);
   void handle_read_body(const boost::system::error_code& error);
   void write(const Message&);
   void handle_write(const boost::system::error_code& error);
   void closeSocket();

   GalconClientErrorHandler m_connectFailed;
   GalconClientMessageHandler m_messageHandler;
   boost::shared_ptr<tcp::resolver::query> m_query;
   std::string m_address;
   std::string m_port;
   IOServicePtr m_ioService;
   boost::shared_ptr<tcp::socket> m_socket;
   boost::shared_ptr<boost::thread> m_workingThreadPtr;
   tcp::resolver::iterator m_endpoint_iterator;
   Message m_message;
   MessagesDeque m_messageDeque;
};

typedef boost::shared_ptr<GalconClient> GalconClientPtr;